package com.shmet.tool.localcalltwo.frame.proxy;

import com.shmet.tool.localcalltwo.frame.context.BeanContext;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author shmet
 * @date 2022/7/28 18:35
 * @desc jdk接口冬天代理
 */
public class BusJdkProxy<T> implements InvocationHandler {

    /**
     * @author shmet
     * @date 2022/7/29
     * @desc 全局代理对象单例池
     */
    private static Map<String, Object> proxySingletonPool = new ConcurrentHashMap<>();

    private Class<T> proxyInterface;

    public BusJdkProxy(Class<T> proxyInterface){
        this.proxyInterface = proxyInterface;
    }

    /**
     * @author shmet
     * @date 2022/7/29
     * @desc 生成代理对象
     */
    public T getProxy() {
        String className = this.proxyInterface.getName();
        if (proxySingletonPool.containsKey(className)) {
            return (T) proxySingletonPool.get(className);
        } else {
            synchronized (proxySingletonPool) {
                if (proxySingletonPool.containsKey(className)) {
                    return (T) proxySingletonPool.get(className);
                } else {
                    T tProxy = (T) Proxy.newProxyInstance(proxyInterface.getClassLoader(), new Class[]{proxyInterface}, this);
                    proxySingletonPool.put(className, tProxy);
                    return tProxy;
                }
            }
        }
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 从约定的参数中，根据基类取实体
        String module = this.getBaseParamByArgs(args);
        String type = this.getServNameByClass(this.proxyInterface);
        // 根据参数取示例对象
        Object instance = BeanContext.getRegBean(module + type);
        if (Objects.nonNull(instance)) {
            // 换成要执行的示例的方法
            Method newMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes());
            return newMethod.invoke(instance, args);
        }
        return null;
    }

    /**
     * @author shmet
     * @date 2022/6/28
     * @desc 获取ser名称
     */
    public String getServNameByClass(Class<?> objClass) {
        return objClass.getSimpleName();
    }

    /**
     * @author shmet
     * @date 2022/6/27
     * @desc 遍历取约定对象，假设关键参数在第一位
     */
    public String getBaseParamByArgs(Object[] args) {
        if (null != args && args.length > 0) {
            return args[0] + "";
        }
        return null;
    }
}
